﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Cube.Data;

namespace CubeForm.AI
{
    class Cross : IPattenMatch
    {
        Cube.Data.Cube cube;
        PattenManager patten;
        public Cross(Cube.Data.Cube cube)
        {
            this.cube = cube;
            patten = new PattenManager(cube);
        }

        List<PositionVector> Sides = new List<PositionVector>
        {
            new PositionVector(0, 1, -1),
            new PositionVector(0, -1, -1),
            new PositionVector(1, 0, -1),
            new PositionVector(-1, 0, -1),
            new PositionVector(0, 1, 1),
            new PositionVector(0, -1, 1),
            new PositionVector(1, 0, 1),
            new PositionVector(-1, 0, 1),
            new PositionVector(1, 1, 0),
            new PositionVector(1, -1, 0),
            new PositionVector(-1, -1, 0),
            new PositionVector(-1, 1, 0)
        };

        public event PattenMatchedDelegate PattenMatched;

        public void Invoke()
        {
            CubeColor bottomColor = cube[new PositionVector(0, 0, -1)].Z; //获取底面颜色
            CubeColor[] sideColors = new CubeColor[]    //侧面颜色
            {
                cube[new PositionVector(0,1,0)].Y,
                cube[new PositionVector(1,0,0)].X,
                cube[new PositionVector(0,-1,0)].Y,
                cube[new PositionVector(-1,0,0)].X
            };
            foreach(var sidecolor in sideColors)
            {
                foreach(var sideblock in Sides)
                {
                    // 若找到带有底色的棱块
                    if (cube[sideblock].X == bottomColor || cube[sideblock].Y == bottomColor || cube[sideblock].Z == bottomColor)
                    {
                        // 找到的不是符合侧面颜色的棱块
                        if (cube[sideblock].X != sidecolor && cube[sideblock].Y != sidecolor && cube[sideblock].Z != sidecolor)
                            continue;   //跳过，继续找
                        int selected_index = cube.FindCubeByPosition(sideblock);
                        var selected_block = cube[selected_index];
                        System.Diagnostics.Debug.WriteLine(sidecolor + ":");
                        System.Diagnostics.Debug.WriteLine("OriginPosition:" + selected_block.Position.X + "," + selected_block.Position.Y + "," + selected_block.Position.Z);
                        var color_vect = selected_block.ColorVector;
                        System.Diagnostics.Debug.WriteLine("OriginColor:" + color_vect.X + "," + color_vect.Y + "," + color_vect.Z);
                        var cross_case = ParaseToBasicCrossPatten(selected_block.Position);
                        System.Diagnostics.Debug.WriteLine("ParasedPosition:" + selected_block.Position.X + "," + selected_block.Position.Y + "," + selected_block.Position.Z);
                        System.Diagnostics.Debug.WriteLine("Case:" + cross_case);
                        var direction = CheckBasicCaseDirection(selected_block.Position, bottomColor);
                        System.Diagnostics.Debug.WriteLine("Direction:" + direction + "\n");
                        switch (direction)
                        {
                            case SideBlockDirection.Positive:
                                switch (cross_case)
                                {
                                    case BasicCrossPatten.Patten1: break;
                                    case BasicCrossPatten.Patten2:
                                        patten._F();
                                        break;
                                    case BasicCrossPatten.Patten3:
                                        patten.F();
                                        break;
                                    case BasicCrossPatten.Patten4:
                                        patten.F();
                                        patten.F();
                                        break;
                                }
                                break;
                            case SideBlockDirection.Nagetive:
                                switch (cross_case)
                                {
                                    case BasicCrossPatten.Patten1:
                                        patten.F();
                                        patten._MU();
                                        patten.F();
                                        patten.MU();
                                        break;
                                    case BasicCrossPatten.Patten2:
                                        patten._MU();
                                        patten.F();
                                        patten.MU();
                                        break;
                                    case BasicCrossPatten.Patten3:
                                        patten.MU();
                                        patten._F();
                                        patten._MU();
                                        break;
                                    case BasicCrossPatten.Patten4:
                                        patten.F();
                                        patten.MU();
                                        patten._F();
                                        patten._MU();
                                        break;
                                }
                                break;
                        }
                    }
                }
                patten.y();
            }
            PattenMatched?.Invoke(patten.GetRecord());
        }

        /// <summary>
        /// 将Cross的各种情况转化为四种基本情况
        /// </summary>
        /// <param name="blockPosition">Cross棱块位置</param>
        /// <returns></returns>
        private BasicCrossPatten ParaseToBasicCrossPatten(PositionVector blockPosition)
        {
            BasicCrossPatten crossPatten = BasicCrossPatten.Not;
            if(blockPosition.Equals(new PositionVector(0, 1, -1)))
                crossPatten = BasicCrossPatten.Patten1;
            if (blockPosition.Equals(new PositionVector(-1, 1, 0)))
                crossPatten = BasicCrossPatten.Patten2;
            if (blockPosition.Equals(new PositionVector(1, 1, 0)))
                crossPatten = BasicCrossPatten.Patten3;
            if (blockPosition.Equals(new PositionVector(0, 1, 1)))
                crossPatten = BasicCrossPatten.Patten4;
            if (blockPosition.Equals(new PositionVector(1, 0, 1)))
            {
                patten.U();
                crossPatten = BasicCrossPatten.Patten4;
            }
            if(blockPosition.Equals(new PositionVector(0, -1, 1)))
            {
                patten.U();
                patten.U();
                crossPatten = BasicCrossPatten.Patten4;
            }
            if(blockPosition.Equals(new PositionVector(-1, 0, 1)))
            {
                patten._U();
                crossPatten = BasicCrossPatten.Patten4;
            }
            if (blockPosition.Equals(new PositionVector(-1, -1, 0)))
            {
                patten._MU();
                patten.F();
                patten.MU();
                crossPatten = BasicCrossPatten.Patten4;
            }
            if (blockPosition.Equals(new PositionVector(1, -1, 0)))
            {
                patten.MU();
                patten._F();
                patten._MU();
                crossPatten = BasicCrossPatten.Patten4;
            }
            if (blockPosition.Equals(new PositionVector(1, 0, -1)))
            {
                patten.R();
                crossPatten = BasicCrossPatten.Patten3;
            }
            if (blockPosition.Equals(new PositionVector(-1, 0, -1)))
            {
                patten._L();
                crossPatten = BasicCrossPatten.Patten2;
            }
            if (blockPosition.Equals(new PositionVector(0, -1, -1)))
            {
                patten.B();
                patten.B();
                patten.U();
                patten.U();
                crossPatten = BasicCrossPatten.Patten4;
            }
            return crossPatten;
        }

        /// <summary>
        /// 棱块方向判断
        /// </summary>
        /// <param name="sideblockPosition">棱块位置</param>
        /// <param name="bottom">底面颜色</param>
        /// <returns></returns>
        private SideBlockDirection CheckBasicCaseDirection(PositionVector sideblockPosition, CubeColor bottom)
        {
            var direction = SideBlockDirection.Nagetive;
            if (sideblockPosition.Equals(new PositionVector(0, 1, -1)))
            {
                direction = cube[sideblockPosition].Z == bottom ? SideBlockDirection.Positive : SideBlockDirection.Nagetive;
            }
            if (sideblockPosition.Equals(new PositionVector(-1, 1, 0)))
            {
                direction = cube[sideblockPosition].X == bottom ? SideBlockDirection.Positive : SideBlockDirection.Nagetive;
            }
            if (sideblockPosition.Equals(new PositionVector(1, 1, 0)))
            {
                direction = cube[sideblockPosition].X == bottom ? SideBlockDirection.Positive : SideBlockDirection.Nagetive;
            }
            if (sideblockPosition.Equals(new PositionVector(0, 1, 1)))
            {
                direction = cube[sideblockPosition].Z == bottom ? SideBlockDirection.Positive : SideBlockDirection.Nagetive;
            }
            return direction;
        }

        enum SideBlockDirection
        {
            /// <summary>
            /// 正向
            /// </summary>
            Positive,
            /// <summary>
            /// 反向
            /// </summary>
            Nagetive
        }

        enum BasicCrossPatten
        {
            Patten1,
            Patten2,
            Patten3,
            Patten4,
            Not
        }
    }
}
